nexus\api\rtapi/
mod.rs

1//! Bindings for Nexus RealTime API.
2//!
3//! # Usage
4//! ```no_run
5//! use nexus::rtapi::{RealTimeApi, GroupType};
6//!
7//! if let Some(rtapi) = RealTimeApi::get() {
8//!     if let Some(group) = rtapi.read_group() {
9//!         let is_squad = matches!(group.group_type, Ok(GroupType::Squad | GroupType::RaidSquad));
10//!     }
11//! }
12//! ```
13
14mod camera;
15pub mod data;
16pub mod event;
17mod game;
18mod group;
19mod player;
20mod world;
21
22pub use self::{camera::*, game::*, group::*, player::*, world::*};
23
24use self::data::RealTimeData;
25use std::ptr::NonNull;
26
27/// Interface for RealTime API.
28#[derive(Debug, Clone, Copy)]
29#[repr(transparent)]
30pub struct RealTimeApi(NonNull<RealTimeData>);
31
32impl RealTimeApi {
33    /// Signature of the RealTime API addon.
34    pub const SIG: i32 = RealTimeData::SIG;
35
36    /// Retrieves the RealTime API interface.
37    #[inline]
38    pub fn get() -> Option<Self> {
39        NonNull::new(RealTimeData::get_ptr().cast_mut()).map(Self)
40    }
41
42    /// Returns a raw pointer to the [`RealTimeData`].
43    #[inline]
44    pub const fn as_ptr(&self) -> *const RealTimeData {
45        self.0.as_ptr()
46    }
47
48    /// Returns a [`NonNull`] to the [`RealTimeData`].
49    #[inline]
50    pub const fn as_non_null(&self) -> NonNull<RealTimeData> {
51        self.0
52    }
53
54    /// Returns a reference to the value.
55    ///
56    /// This is dangerous since the memory is volatile and holding a reference can easily violate aliasing rules.
57    ///
58    /// # Safety
59    /// See [NonNull::as_ref].
60    #[inline]
61    pub unsafe fn as_ref(&self) -> &RealTimeData {
62        self.0.as_ref()
63    }
64
65    /// Checks whether the link is active.
66    #[inline]
67    pub fn is_active(&self) -> bool {
68        unsafe { (*self.as_ptr()).game_build != 0 }
69    }
70
71    /// Reads the [`GameData`].
72    #[inline]
73    pub fn read_game(&self) -> Option<GameData> {
74        self.is_active()
75            .then(|| unsafe { GameData::read(self.as_ptr()) })
76    }
77
78    /// Reads the [`WorldData`].
79    #[inline]
80    pub fn read_world(&self) -> Option<WorldData> {
81        self.is_active()
82            .then(|| unsafe { WorldData::read(self.as_ptr()) })
83    }
84
85    /// Reads the [`GroupData`].
86    #[inline]
87    pub fn read_group(&self) -> Option<GroupData> {
88        self.is_active()
89            .then(|| unsafe { GroupData::read(self.as_ptr()) })
90    }
91
92    /// Reads the [`PlayerData`].
93    #[inline]
94    pub fn read_player(&self) -> Option<PlayerData> {
95        self.is_active()
96            .then(|| unsafe { PlayerData::read(self.as_ptr()) })
97    }
98
99    /// Reads the [`CameraData`].
100    #[inline]
101    pub fn read_camera(&self) -> Option<CameraData> {
102        self.is_active()
103            .then(|| unsafe { CameraData::read(self.as_ptr()) })
104    }
105}